package models;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.apache.commons.lang.ArrayUtils;

/**
 * The persistent class for the doc_file database table.
 * 
 */
@Entity
@Table(name = "DOC_FILE")
public class DocFile implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @TableGenerator(
            name = "DOC_FILE_SEQ",
            table = "SEQUENCE",
            pkColumnName = "NAME",
            pkColumnValue = "DOC_FILE_SEQ",
            valueColumnName = "CNT",
            initialValue = 10000,
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "DOC_FILE_SEQ")
    @Column(unique = true, nullable = false)
    private int id;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATE_D")
    private Date createD;

    @Column(name = "DOC_ID")
    private int docId;

    @Column(name = "FILE_TYPE")
    private int fileType;

    @Column(length = 200)
    private String location;

    private int processed;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "UPDATE_D")
    private Date updateD;

    public DocFile() {
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getCreateD() {
        return this.createD;
    }

    public void setCreateD(Date createD) {
        this.createD = createD;
    }

    public int getDocId() {
        return this.docId;
    }

    public void setDocId(int docId) {
        this.docId = docId;
    }

    public ContentType getFileType() {
        return ContentType.values()[this.fileType];
    }

    public void setFileType(ContentType fileType) {
        this.fileType = fileType.ordinal();
    }

    public String getLocation() {
        return this.location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Date getUpdateD() {
        return this.updateD;
    }

    public void setUpdateD(Date updateD) {
        this.updateD = updateD;
    }

    public ProcessStatus getProcessed() {
        return ProcessStatus.values()[this.processed];
    }

    public void setProcessed(ProcessStatus processed) {
        this.processed = processed.ordinal();
    }

    public static enum ProcessStatus {
        NOT_PROCESSED, // File is new, needs to be processed
        PROCESSED, // File has been processed
    }

    public static enum ContentType {
        ANY(new String[] {}, false, false), // 0 - internal use only
        PDF(new String[] { "application/pdf", "application/acrobat", "application/x-pdf", "application/vnd.pdf",
                "text/pdf", "text/x-pdf" }, true, false), // 1 -
        WORD(new String[] { "application/vnd.ms-word" }, false, false), // 2 -
        HTML(new String[] { "text/html" }, false, false), // 3 -
        TEXT(new String[] { "text/plain" }, false, false), // 4 -
        XML(new String[] { "text/xml" }, false, false), // 5 -
        EXCEL(new String[] { "application/vnd.ms-excel",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, false, false), // 6
        JPEG(
                new String[] { "image/jpeg", "image/pipeg", "image/pjpeg", "application/jpg", "application/x-jpg" },
                true,
                true), // 7 -
        TIFF(new String[] { "image/tiff", "image/tif", "image/x-tif", "image/x-tiff", "application/tif",
                "application/tiff", "application/x-tif", "application/x-tiff" }, true, true), // 8
        GIF(new String[] { "image/gif" }, true, true), // 9 -
        BMP(new String[] { "image/bmp", "image/ms-bmp", "image/x-bmp", "image/x-ms-bmp", "image/x-win-bitmap",
                "image/x-windows-bmp", "image/x-xbitmap", "application/bmp", "application/x-bmp" }, false, true), // 10
        PNG(new String[] { "image/png", "application/png", "application/x-png", "image/x-png" }, true, true), // 11
        ZIP(new String[] { "application/zip", "application/octet-stream" }, false, false), // 12
        RAR(
                new String[] { "application/rar", "application/x-rar-compressed", "application/octet-stream" },
                false,
                false) // 13
        ;
        private String[] contentTypes = null;

        private boolean borrowerDocsAccepted = false;

        private boolean imageFile = false;

        private ContentType(String[] pContentTypes, boolean pBorrowerDocsAccepted, boolean pImageFile) {
            contentTypes = pContentTypes;
            borrowerDocsAccepted = pBorrowerDocsAccepted;
            imageFile = pImageFile;
        }

        public String[] getContentTypes() {
            return this.contentTypes;
        }

        public String getContentType() {
            if (this.contentTypes.length > 0)
                return this.contentTypes[0];
            return "";
        }

        public boolean isBorrowerDocsAccepted(Doc.Type docType) {

            // Allow to upload excel files in bank statements
            if (EXCEL.equals(this)
                    && (Doc.Type.BANK_STATEMENT.equals(docType) || Doc.Type.COM_BANK_STATEMENT.equals(docType))) {
                return true;
            }

            return borrowerDocsAccepted;
        }

        public boolean isImageFile() {
            return imageFile;
        }

        /**
         * Gets the TLDoc.ContentType enum value for the given mime type string
         * 
         * @param contentType
         *            MIME type
         */
        public static ContentType determineContentType(String contentType) {
            for (ContentType ct : ContentType.values()) {
                if (ArrayUtils.contains(ct.getContentTypes(), contentType))
                    return ct;
            }
            return null;
        }

        /**
         * Determines if the given content type is a valid document format
         * 
         * @param contentType
         *            MIME type
         */
        public static boolean isAcceptedContentType(ContentType contentType, Doc.Type docType) {
            return contentType != null && contentType.isBorrowerDocsAccepted(docType);
        }
    }

}